﻿using DenseCRF;
using FCN;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CNN
{
    class Program
    {
        static void Main(string[] args)
        {
             

            float[,] X = new float[,] { { 0.5f}};
            float[,] Y = new float[,] { { -0.0053f } };
            float[,] W = new float[,] { { 0.1f } };
            //   float[,] temp= Matrix.convnValid(X, W, 1, 0);
            float[,] temp = Matrix.convnValid(X, Y, 1, 0);

            float[,] TT = new float[,] { { -0.5160f, -0.5160f }, { -0.5160f, -0.7289f, } };
            float[,] Ta=   MESBackwrad(X, Y, TT);
          
            temp = Matrix.convnValid(Ta, Y, 1, 0);
            //  FCNTrain();
            FCNtest();
              // CNNCovTrain5x5();//全卷积训练
              //CNNFULLTrain5x5();//全连接训练
              // CNNtest();//全连接测试

            //   CNNcovtest();//全卷积测试
        }
       static float[,] MESBackwrad(float[,] X, float[,] Y, float[,] temp)
        {
            int size = 2;
            float[,] W = new float[size, size];
            for (var i = 0; i < size; i++)
                for (var j = 0; j < size; j++)
                {
                    float[,] ff = new float[temp.GetLength(0), temp.GetLength(1)];
                    float sum = 0f;
                    for (var x = i; x < i+size; x++)
                        for (var y = j; y < j+size; y++)
                        {
                            //if (x >= Y.GetLength(0) || y >= Y.GetLength(1))
                            //    continue;
                            ff[x-i, y-j] = -2 * X[x, y] * (Y[x - i, y - j] - temp[x - i, y - j]);
                            sum += ff[x - i, y - j];
                        }
                    W[i, j] = sum / (size * 2);
                }

            return W;
        }
        static void FCNtest()
        {
          
           // outputlayer output = new outputlayer(false, 12, 2, 5);
            //  output.isFull = true;
          //  layers.Add(output);
            System.IO.StreamReader sr = new System.IO.StreamReader("tagjixue.fcn", Encoding.UTF8);
            string strmode = sr.ReadToEnd();
            sr.Close();
            cnnweights cnnw = Newtonsoft.Json.JsonConvert.DeserializeObject<cnnweights>(strmode);
            NeuralNetwork cnn = new NeuralNetwork();
            string file = "ii12.jpg";
            Matrix[] anno1 = util.readpnggetMatrix(file,false);
            int channl = anno1.GetLength(0);
            int wcount = 6;
            for (int ha = 0; ha < anno1.GetLength(0); ha++)
            {
                anno1[ha].values = ImgUtil.Bilinear(anno1[ha].values, 512, 512);
                
            }
            List<Layer> layers = new List<Layer>();

            layers.Add(new convlayer(1, 2, 5, 1, channl * wcount, false));//256
            layers.Add(new Poolinglayer(2, channl * wcount, channl * wcount));//128
            layers.Add(new convlayer(1, 2, 5, channl * wcount, channl * wcount, false));//
            layers.Add(new Poolinglayer(2, channl * wcount, channl * wcount));// 64
            layers.Add(new convlayer(1, 2, 5, channl * wcount, channl * wcount, false));//
            layers.Add(new Poolinglayer(2, channl * wcount, channl * wcount));//32
            layers.Add(new convlayer(1, 0, 5, channl * wcount, channl * wcount, false));//28
            layers.Add(new Poolinglayer(2, channl * wcount, channl * wcount));//14
            layers.Add(new convlayer(1, 0, 5, channl * wcount, channl * wcount, false));//10
            layers.Add(new Poolinglayer(2, channl * wcount, channl * wcount));//5 
            layers.Add(new outputlayer(false,  channl * wcount, 2,5, false));
            cnn.FCNidentify(layers, cnnw, anno1, activateFun.sigmoid);

        }
        static void FCNTrain()
        {
            string[] Directs = System.IO.Directory.GetDirectories("res");

            int max=0;
            foreach (string dd in Directs)
            {
                string[] files = System.IO.Directory.GetFiles(dd); 
                int index = Convert.ToInt32(dd.Split('\\')[1]);
                if (max < index)
                    max = index;


            }
            int channl = 3;
            List<Matrix> annolist = new List<Matrix>();
            List<lable> las = new List<lable>();
            foreach (string dd in Directs)
            {
               
                string[] files = System.IO.Directory.GetFiles(dd);
                int index = Convert.ToInt32(dd.Split('\\')[1]);
            
               

                List<Matrix> matrices = new List<Matrix>();
                foreach (string file in files)
                {
                    lable la = new lable();
                    la.tag = index;
                    la.output = new float[max];
                    la.output[index - 1] = 1;
                  
                    Matrix[] anno1 = util.readpnggetMatrix(file, false);
                    channl = anno1.GetLength(0);
                    for (int ha = 0; ha < anno1.GetLength(0); ha++)
                    {
                        anno1[ha].values = ImgUtil.Bilinear(anno1[ha].values, 256, 256);
                        //  im1[ha].values= ImgUtil.Bilinear(im1[ha].values, 64, 64);
                        annolist.Add(anno1[ha]);
                        las.Add(la);
                    }
                    
                   


                }
                
            }
            List<Layer> layers = new List<Layer>();
            int wcount = 6;
            layers.Add(new convlayer(1, 2, 5, 1, channl* wcount));//256
            layers.Add(new Poolinglayer(2, channl * wcount, channl * wcount));//128
            layers.Add(new convlayer(1, 2, 5, channl * wcount, channl * wcount));//
            layers.Add(new Poolinglayer(2, channl * wcount, channl * wcount));// 64
            layers.Add(new convlayer(1, 2, 5, channl * wcount, channl * wcount));//
            layers.Add(new Poolinglayer(2, channl * wcount, channl * wcount));//32
            layers.Add(new convlayer(1, 0, 5, channl * wcount, channl * wcount));//28
            layers.Add(new Poolinglayer(2, channl * wcount, channl * wcount));//14
            layers.Add(new convlayer(1, 0, 5, channl * wcount, channl * wcount));//10
            layers.Add(new Poolinglayer(2, channl * wcount, channl * wcount));//5 
            outputlayer output = new outputlayer(false, channl * wcount, max, 5);
            //  output.isFull = true;
            layers.Add(output);
            NeuralNetwork cn = new NeuralNetwork();
            cnnweights cnnw = cn.Train(layers, annolist.ToArray(), las.ToArray(), 1,activateFun.sigmoid);
            string str = Newtonsoft.Json.JsonConvert.SerializeObject(cnnw);
            System.IO.StreamWriter sw = new System.IO.StreamWriter("tagjixue.fcn", false, Encoding.UTF8);
            sw.Write(str);
            sw.Close();
        }
        static void CNNcovtest()
        {
            Minst.MinstImgArr trainImg = Minst.read_Img("D:\\caffe\\Minst\\t10k-images.idx3-ubyte");
            Minst.MinstLabelArr trainLabel = Minst.read_Lable("D:\\caffe\\Minst\\t10k-labels.idx1-ubyte");
            List<Layer> layers = new List<Layer>();//28

            layers.Add(new convlayer(1, 0, 5, 1, 6));//24
            layers.Add(new Poolinglayer(2, 6, 6));//12
            layers.Add(new convlayer(1, 0, 5, 6, 12));//8
            layers.Add(new Poolinglayer(2, 12, 12));//4
            outputlayer output = new outputlayer(false, 12, 10,4);
             
            layers.Add(output);

            NeuralNetwork cnn = new NeuralNetwork();
            System.IO.StreamReader sr = new System.IO.StreamReader("tagjixue.mode", Encoding.UTF8);
            string strmode = sr.ReadToEnd();
            sr.Close();
            cnnweights cnnw = Newtonsoft.Json.JsonConvert.DeserializeObject<cnnweights>(strmode);
            Matrix anno = new Matrix();
            anno.values = trainImg.ImgPtr[1].ImgData;
            int max = cnn.CNNidentify(layers, cnnw, anno);
        }
        static void CNNtest()
        {
            Minst.MinstImgArr trainImg = Minst.read_Img("D:\\caffe\\Minst\\t10k-images.idx3-ubyte");
            Minst.MinstLabelArr trainLabel = Minst.read_Lable("D:\\caffe\\Minst\\t10k-labels.idx1-ubyte");
            List<Layer> layers = new List<Layer>();//28

            layers.Add(new convlayer( 1, 0, 5, 1, 6));//24
            layers.Add(new Poolinglayer( 2, 6, 6));//12
            layers.Add(new convlayer( 1, 0, 5, 6, 12));//8
            layers.Add(new Poolinglayer( 2, 12, 12));//4
            outputlayer output = new outputlayer(true,4 * 4 * 12, 10);
            output.isFull = true;
            layers.Add(output);

            NeuralNetwork cnn = new NeuralNetwork();
            System.IO.StreamReader sr = new System.IO.StreamReader("tagjixue.mode", Encoding.UTF8);
            string strmode = sr.ReadToEnd();
            sr.Close();
            cnnweights cnnw= Newtonsoft.Json.JsonConvert.DeserializeObject<cnnweights>(strmode);
            Matrix anno = new Matrix();
             anno.values = trainImg.ImgPtr[1].ImgData;
            int max=cnn.CNNidentify(layers, cnnw, anno);
        }
        static void CNNFULLTrain5x5()
        {
            Minst.MinstImgArr trainImg = Minst.read_Img("D:\\caffe\\Minst\\train-images.idx3-ubyte");
            Minst.MinstLabelArr trainLabel = Minst.read_Lable("D:\\caffe\\Minst\\train-labels.idx1-ubyte");


            List<Layer> layers = new List<Layer>();

            layers.Add(new convlayer(1, 0, 5, 1, 6));//32
            layers.Add(new Poolinglayer( 2, 6, 6));//16
            layers.Add(new convlayer(1, 0, 5, 6, 12));//16
            layers.Add(new Poolinglayer( 2, 12, 12));//14 
            outputlayer output = new outputlayer(true, 4 * 4 * 12, 10);
          //  output.isFull = true;
            layers.Add(output);
            Matrix[] anno = new Matrix[50];
            lable[] lables = new lable[50];

            NeuralNetwork cn = new NeuralNetwork();
            for (int a = 0; a < 50; a++)
            {
                anno[a] = new Matrix();
                anno[a].values = trainImg.ImgPtr[a].ImgData;
                lables[a] = new lable();
                lables[a].output = trainLabel.LabelPtr[a].LabelData;
                lables[a].tag = trainLabel.LabelPtr[a].l;

            }
            cnnweights cnnw= cn.Train(layers, anno, lables, 1);
            string str = Newtonsoft.Json.JsonConvert.SerializeObject(cnnw);
            System.IO.StreamWriter sw = new System.IO.StreamWriter("tagjixue.mode", false, Encoding.UTF8);
            sw.Write(str);
            sw.Close();
        }
        static void CNNCovTrain5x5()
        {
            Minst.MinstImgArr trainImg = Minst.read_Img("D:\\caffe\\Minst\\train-images.idx3-ubyte");
            Minst.MinstLabelArr trainLabel = Minst.read_Lable("D:\\caffe\\Minst\\train-labels.idx1-ubyte");


            List<Layer> layers = new List<Layer>();

            layers.Add(new convlayer(1, 0, 5, 1, 6));//32
            layers.Add(new Poolinglayer(2, 6, 6));//16
            layers.Add(new convlayer(1, 0, 5, 6, 12));//16
            layers.Add(new Poolinglayer(2, 12, 12));//14 
            outputlayer output = new outputlayer(false,  12, 10,4);
            //  output.isFull = true;
            layers.Add(output);
            Matrix[] anno = new Matrix[50];
            lable[] lables = new lable[50];

            NeuralNetwork cn = new NeuralNetwork();
            for (int a = 0; a < 50; a++)
            {
                anno[a] = new Matrix();
                anno[a].values = trainImg.ImgPtr[a].ImgData;
                lables[a] = new lable();
                lables[a].output = trainLabel.LabelPtr[a].LabelData;
                lables[a].tag = trainLabel.LabelPtr[a].l;

            }
            cnnweights cnnw = cn.Train(layers, anno, lables, 1);
            string str = Newtonsoft.Json.JsonConvert.SerializeObject(cnnw);
            System.IO.StreamWriter sw = new System.IO.StreamWriter("tagjixue.mode", false, Encoding.UTF8);
            sw.Write(str);
            sw.Close();
        }

    }
}
